package com.bxl.chooser.bean;

import org.apache.commons.lang3.StringUtils;

/**
 * <>
 *
 * @author baixl
 * @date 2021/3/25
 */
public class AppInfo {
    /**
     * 机器状态
     */
    private AppState state;

    /**
     * 提交的日志的term-应该持久化，从本地读取
     */
    private Integer commitTerm;
    /**
     * 当前任期-应该持久化，从本地读取
     */
    private Integer term;
    /**
     * 投票给谁
     */
    private String votedFor;

    private String appId;

    private MessageContainer messages;

    public AppInfo(AppState state, int logIndex, int commitLogIndex, Integer commitTerm, Integer term, String votedFor, String appId) {
        this.state = state;
        this.commitTerm = commitTerm;
        this.term = term;
        this.votedFor = votedFor;
        this.appId = appId;
        messages = new MessageContainer();
    }

    public enum AppState {
        FOLLOWER("FOLLOWER", "跟随者"), LEADER("LEADER", "领导者"), CANDIDATE("CANDIDATE", "跟随者");
        private String state;
        private String desc;

        AppState(String state, String desc) {
            this.state = state;
            this.desc = desc;
        }

        public String getState() {
            return state;
        }

        public String getDesc() {
            return desc;
        }
    }

    public synchronized boolean voteSelf() {
        //没有投票给别人
        if (StringUtils.isEmpty(this.votedFor)) {
            setState(AppInfo.AppState.CANDIDATE);
            this.votedFor = this.appId;
            return true;
        }
        //投票给别人，等待心跳
        return false;

    }

    /**
     * 根据索引查询消息
     * @param index
     * @return
     */
    public MessageBean getMsg(int index) {
        return messages.getMessage(index);
    }

    /**
     * 根据消息ID查询消息
     * @param messageId
     * @return
     */
    public MessageBean getMsg(String messageId) {
        return messages.getMessage(messageId);
    }

    /**
     * 设置自己为leader
     */
    public synchronized void leader() {
        setState(AppState.LEADER);
        this.votedFor = null;
        System.out.println(String.format("appId:%s is leader", appId));
    }

    /**
     * 降级为follower
     */
    public synchronized void follower() {
        setState(AppState.FOLLOWER);
        this.votedFor = null;
        System.out.println(String.format("appId:%s is follower", appId));
    }

    public synchronized void setVotedFor(String votedFor) {
        if (StringUtils.isEmpty(this.votedFor)) {
            this.votedFor = votedFor;
        }

    }

    public synchronized void clearVotedFor() {
        if (StringUtils.isNoneEmpty(this.votedFor)) {
            this.votedFor = null;
        }
    }


    public boolean addMessage(MessageBean message) {
        synchronized (this.messages) {
            return messages.addMessage(message, this);
        }
    }

    public boolean commitMessage(int commitIndex) {
        synchronized (this.messages) {
            return messages.commitMessage(commitIndex, this);
        }

    }

    public synchronized boolean deleteMessage(String messageId) {
        return messages.deleteMessage(messageId);
    }

    public boolean rollback(String messageId) {
        return messages.rollback(messageId);
    }

    public void commitLogIndexIncrease() {
        synchronized (this.messages){
            messages.commitLogIndexIncrease(this);
        }
        
    }

    public void termIncrease() {
        synchronized (this.term) {
            this.term++;
        }
    }

    public AppState getState() {
        return state;
    }

    public void setState(AppState state) {
        this.state = state;
    }

    public int getLogIndex() {
        return messages.getLogIndex();
    }


    public int getCommitLogIndex() {
        return messages.getCommitLogIndex();
    }


    public int getCommitTerm() {
        return commitTerm;
    }

    public void setCommitTerm(int commitTerm) {
        this.commitTerm = commitTerm;
    }

    public int getTerm() {
        return term;
    }

    public void setTerm(int term) {
        this.term = term;
    }

    public String getVotedFor() {
        return votedFor;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }


}
